/*****************************************************************************/
/**
 *  @file   ImportSPHFileList.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "ImportSPHFileList.h"
#include <kvs/StructuredVolumeObject>
#include <kvs/Vector3>
#include <kvs/AnyValueArray>
#include "SPHFile.h"
#include "SPHFileList.h"


namespace kvsbloodvis
{

namespace util
{

/*===========================================================================*/
/**
 *  @brief  Imports SPH files as a structured volume object.
 *  @param  sph_list [in] SPH file list
 *  @return structured volume object
 */
/*===========================================================================*/
kvs::StructuredVolumeObject ImportSPHFileList( const SPHFileList& sph_list )
{
    const kvs::Vector3d global_org = sph_list.org();
    const kvs::Vector3d global_pitch = sph_list.pitch();
    const kvs::Vector3d global_max = sph_list.max();
    const kvs::Vector3ui resolution = sph_list.resolution();
    const kvs::UInt32 values_size = resolution.x() * resolution.y() *resolution.z();
    const size_t veclen = sph_list.svType() == 1 ? 1 : 3;
    kvs::ValueArray<kvs::Real32> values( values_size * veclen );
    values.fill(0);

    kvs::Real32 min_value = kvs::Value<kvs::Real32>::Max();
    kvs::Real32 max_value = kvs::Value<kvs::Real32>::Min();

    for ( size_t index = 0; index < sph_list.size(); index++ )
    {
        const kvs::Vector3d local_max = sph_list.sph( index ).max();
        const kvs::Vector3d local_org = sph_list.sph( index ).org();
        const kvs::Vector3d local_pitch = sph_list.sph( index ).pitch();
        const kvs::AnyValueArray local_data = sph_list.sph( index ).data();
        const size_t I_start = ( local_org[0] - global_org[0] ) / global_pitch[0];
        const size_t J_start = ( local_org[1] - global_org[1] ) / global_pitch[1];
        const size_t K_start = ( local_org[2] - global_org[2] ) / global_pitch[2];
        const size_t i_end = local_max[0];
        const size_t j_end = local_max[1];
        const size_t k_end = local_max[2];
        for ( size_t k = 0, K = K_start; k < k_end; k++, K++ )
        {
            for ( size_t j = 0, J = J_start; j < j_end; j++, J++ )
            {
                for ( size_t i = 0, I = I_start; i < i_end; i++, I++ )
                {
                    const size_t local_index = k * local_max[0] * local_max[1] + j * local_max[0] + i;
                    const size_t global_index = K * global_max[0] * global_max[1] + J * global_max[0] + I;
                    kvs::Real32 temp_value = 0.0f;
                    for ( size_t v = 0; v < veclen; v++ )
                    {
                        const kvs::Real32 value = local_data.at<kvs::Real32>( veclen * local_index + v );
                        values[ veclen * global_index + v ] = value;
                        temp_value += value * value;
                    }

                    temp_value = std::sqrt( temp_value );
                    min_value = kvs::Math::Min( min_value, temp_value );
                    max_value = kvs::Math::Max( max_value, temp_value );
                }
            }
        }
    }

    kvs::StructuredVolumeObject volume;
    volume.setGridType( kvs::StructuredVolumeObject::Uniform );
    volume.setVeclen( veclen );
    volume.setResolution( resolution );
    volume.setValues( values );
    volume.setMinMaxValues( min_value, max_value );
    volume.updateMinMaxCoords();

    return volume;
}

} // end of namespace util

} // end of namespace kvsbloodvis
